# NOTES
# These are the work and tests corresponding to each individual question.
# Most code is available in the respective files.


# BASIC 1
class Numeric
  def squared
    return self * self
  end
end

# BASIC 2
#	This is because the string "1:00 pm" is not of the class Time.
#	In fact, Time.parse is a class method, not a global method,
#		so even an object of class Time wouldn't work.
#	There would need to be an instance method for the String class called parse
#		that uses "self".

# BASIC 3
  def initialize(name,showtime)
    @name = name
    if showtime.is_a?(Time)
        @showtime = showtime
    elsif showtime.is_a?(String)
        @showtime = Time.parse(showtime)
    else
        raise ArgumentError, "Invalid time input!"
	end
  end

# MODULES 1
  def <=>(x)
    return showtime<=>x.showtime
  end
  
# MODULES 2
  include Comparable
# TESTS
puts movies[1].between?(movies[3],movies[2])
puts movies[0] < movies[1]
puts movies[0] <= movies[1]
puts movies[0] == movies[10]

# MODULES 3
#	It works because the method was mixed-in with Comparable
movies.sort.each do |movie|
  puts movie.name_and_showtime
end

# FUNCTIONAL 1
module Enumerable
  def group_by
    group = {}
    self.each do |item|
      result = yield(item)
	  if group.has_key?(result)
	    group[result] << item
	  else
	    group[result] = [item]
	  end
    end
	return group
  end
end
# TESTS
a = %w(apple banana cherry alice bob carol alpha bravo charlie)
puts a.group_by{ |x| x[0,1].to_s }.inspect

# FUNCTIONAL 2
puts pp(movies.group_by{ |x| x.name })

# FUNCTIONAL 3
puts pp(movies.select { |x| x.showtime > Time.parse("5:00 pm") })
puts movies.select { |x| x.showtime > Time.parse("5:00 pm") }.size
puts movies.select { |movie| movie.showtime > Time.parse("5:00 pm") }.map { |x| x.name }.uniq.inspect

# ITERATORS 1
  def each_even
    yield(self.select { |x| x % 2 == 0 })
  end
# TESTS
[1, 2, 3, 4, 5, 6].each_even do |num|
  puts num
end

# ITERATORS 2
  def each_grouped_by_first_letter
    group = self.group_by { |x| x[0,1].to_s }
    group.to_a.each do |item|
		yield(item)
	end
  end
# TESTS
a = %w(apple banana cherry alice bob carol alpha bravo charlie)
a.each_grouped_by_first_letter do |letter, words|
  puts "#{letter} : #{words.join(' ')}"
end

# EXTENDING CLASSES
h = IndifferentHash.new
h[:foo] = 3
puts h["foo"]
h["foo"] = 4
puts h[:foo]

# EXTENSIONS 1
# PRE-TESTS
x=""
puts x.empty?	# => true
x=" "
puts x.empty?	# => false
x=nil
puts x.empty?	# => NoMethodError
# METHODS
class Object
	def blank?
		if self.respond_to?("empty?")
			return self.empty?
		elsif self == nil
			return true
		else
			return false
		end
	end
end
class String
	def blank?
		if super
			return true
		elsif self.strip.blank?
			return true
		else
			return false
		end
	end
end
# POST-TESTS
x=""
puts x.blank?	# => true
x=" "
puts x.blank?	# => true
x=" \t\n"
puts x.blank?	# => true
x=nil
puts x.blank?	# => true
x=["hello"]
puts x.blank?	# => false